﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="ApprovalControllerTests.cs" company="DST Nexdox">
//   Copyright (c) DST Nexdox. All rights reserved.
// </copyright>
// <summary>
//   Defines the ApprovalControllerTests type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace UnityWebTests.Controllers
{
  using System;
  using System.Collections.Generic;
  using System.Web.Mvc;
  using Entities;
  using Exceptions;
  using FluentAssertions;
  using Logging;
  using Moq;
  using NUnit.Framework;
  using ServiceInterfaces;
  using UnityWeb.Controllers;
  using UnityWeb.Models.Approval;
  using UnityWeb.Models.Shared;

  [TestFixture]
  public class ApprovalControllerTests : ControllerTestsBase
  {
    private Mock<IApprovalService> approvalService;
    private Mock<IDocumentService> documentService;
    private Mock<ICartItemService> cartItemService;
    private Mock<ILogger> logger; 
    private ApprovalController approvalController;
    private ApproveDocumentsViewModel approveDocumentsViewModel;

    [SetUp]
    public void SetUp()
    {
      this.approvalService = new Mock<IApprovalService>();
      this.documentService = new Mock<IDocumentService>();
      this.cartItemService = new Mock<ICartItemService>();
      this.logger = new Mock<ILogger>();
      this.approvalController = new ApprovalController(this.approvalService.Object, this.documentService.Object, this.cartItemService.Object, this.logger.Object);

      this.approveDocumentsViewModel = new ApproveDocumentsViewModel
      {
        ApproveDocumentViewModel = new List<ApproveDocumentViewModel>
                                                                    {
                                                                      new ApproveDocumentViewModel
                                                                        {
                                                                          DocumentId = "guid1",
                                                                          Selected = true
                                                                        },
                                                                        new ApproveDocumentViewModel
                                                                        {
                                                                          DocumentId = "guid2",
                                                                          Selected = false
                                                                        }
                                                                    },
                                                                    Grid = "grid",
                                                                    Page = "1"
      };

      this.SetControllerContext(this.approvalController);
      MockHttpContext.SetupGet(x => x.Session["CartId"]).Returns("testUser");
      MockHttpContext.SetupGet(x => x.User.Identity.Name).Returns("testUser");
      MockHttpContext.SetupGet(x => x.Session["testUser"]).Returns("testUser");
    }

    [Test]
    public void GivenAnApprovalcontroller_WhenITryToApproveADocument_AndTheDocumentIsAlreadyApproved_IGetTheCorrectViewReturned()
    {
      this.approvalService.Setup(
        a =>
        a.ApproveDocument(
        It.IsAny<String>(),
          "guid1",
          It.IsAny<String>(),
          It.IsAny<String>(),
          It.IsAny<String>())).Throws<DocumentAlreadyApprovedException>();

      var result = (PartialViewResult)this.approvalController.Document(this.approveDocumentsViewModel);
      var model = (DocumentWarningsViewModel)result.Model;
      model.DocumentsAlreadyApproved.Should().Be("guid1");
      model.DocumentsAlreadyRejected.Should().Be(String.Empty);
      model.DocumentsApproved.Should().Be(0);
      model.DocumentsRejected.Should().Be(0);
      result.ViewName.Should().Be("_DocumentWarnings");
    }

    [Test]
    public void GivenAnApprovalcontroller_WhenITryToApproveADocument_AndTheDocumentIsAlreadyRejected_IGetTheCorrectViewReturned()
    {
      this.approvalService.Setup(
        a =>
        a.ApproveDocument(
          It.IsAny<String>(),
          "guid1",
          It.IsAny<String>(),
          It.IsAny<String>(),
          It.IsAny<String>())).Throws<DocumentAlreadyRejectedException>();

      var result = (PartialViewResult)this.approvalController.Document(this.approveDocumentsViewModel);
      var model = (DocumentWarningsViewModel)result.Model;
      model.DocumentsAlreadyApproved.Should().Be(String.Empty);
      model.DocumentsAlreadyRejected.Should().Be("guid1");
      model.DocumentsApproved.Should().Be(0);
      model.DocumentsRejected.Should().Be(0);
      result.ViewName.Should().Be("_DocumentWarnings");
    }

    [Test]
    public void GivenAnApprovalcontroller_WhenITryToApproveADocument_IGetTheCorrectViewReturned()
    {
      this.approvalService.Setup(
        a =>
        a.ApproveDocument(
        It.IsAny<String>(),
          "guid1",
          It.IsAny<String>(),
          It.IsAny<String>(),
          It.IsAny<String>()));

      var result = (PartialViewResult)this.approvalController.Document(this.approveDocumentsViewModel);
      var model = (DocumentWarningsViewModel)result.Model;
      model.DocumentsAlreadyApproved.Should().Be(String.Empty);
      model.DocumentsAlreadyRejected.Should().Be(String.Empty);
      model.DocumentsApproved.Should().Be(1);
      model.DocumentsRejected.Should().Be(0);
      result.ViewName.Should().Be("_DocumentWarnings");
    }

    [Test]
    public void GivenAnApprovalcontroller_WhenITryToApproveAGrid_AndTheGridContaintsADocumentThatIsAlreadyApproved_IGetTheCorrectViewReturned()
    {
      this.documentService.Setup(d => d.GetDocuments("grid")).Returns(new List<Document>
                                                                    {
                                                                      new Document
                                                                        {
                                                                          DocType = new DocType(),
                                                                          SubDocType = new SubDocType(),
                                                                          ManCo = new ManCo(),
                                                                          DocumentId = "guid1"
                                                                        }
                                                                    });
      var approvalResults = new BatchApprovalResults();
      approvalResults.AlreadyApprovedDocuments.Add("guid1");

      this.approvalService.Setup(a => a.ApproveGrid(It.IsAny<String>(), It.IsAny<String>())).Returns(approvalResults);

      var result = (PartialViewResult)this.approvalController.Grid("grid");
      var model = (DocumentWarningsViewModel)result.Model;
      model.DocumentsAlreadyRejected.Should().Be(string.Empty);
      model.DocumentsAlreadyApproved.Should().Be("guid1");
      model.DocumentsApproved.Should().Be(0);
      model.DocumentsRejected.Should().Be(0);
      result.ViewName.Should().Be("_DocumentWarnings");
    }

    [Test]
    public void GivenAnApprovalcontroller_WhenITryToApproveAGrid_AndTheGridContaintsADocumentThatIsAlreadyRejected_IGetTheCorrectViewReturned()
    {
      this.documentService.Setup(d => d.GetDocuments("grid")).Returns(new List<Document>
                                                                    {
                                                                      new Document
                                                                        {
                                                                          DocType = new DocType(),
                                                                          SubDocType = new SubDocType(),
                                                                          ManCo = new ManCo(),
                                                                          DocumentId = "guid1"
                                                                        }
                                                                    });

      var approvalResults = new BatchApprovalResults();
      approvalResults.AlreadyRejectedDocuments.Add("guid1");

      this.approvalService.Setup(a => a.ApproveGrid(It.IsAny<String>(), It.IsAny<String>())).Returns(approvalResults);

      var result = (PartialViewResult)this.approvalController.Grid("grid");
      var model = (DocumentWarningsViewModel)result.Model;
      model.DocumentsAlreadyApproved.Should().Be(string.Empty);
      model.DocumentsAlreadyRejected.Should().Be("guid1");
      model.DocumentsApproved.Should().Be(0);
      model.DocumentsRejected.Should().Be(0);
      result.ViewName.Should().Be("_DocumentWarnings");
    }

    [Test]
    public void GivenAnApprovalcontroller_WhenITryToApproveAGrid_IGetTheCorrectViewReturned()
    {
      var approvalResults = new BatchApprovalResults();
      approvalResults.ApprovedDocuments.Add("guid1");

      this.approvalService.Setup(a => a.ApproveGrid(It.IsAny<String>(), It.IsAny<String>())).Returns(approvalResults);

      var result = (PartialViewResult)this.approvalController.Grid("grid");
      var model = (DocumentWarningsViewModel)result.Model;
      model.DocumentsAlreadyApproved.Should().Be(string.Empty);
      model.DocumentsAlreadyRejected.Should().Be(string.Empty);
      model.DocumentsApproved.Should().Be(1);
      model.DocumentsRejected.Should().Be(0);
      result.ViewName.Should().Be("_DocumentWarnings");
    }

    [Test]
    public void GivenAnApprovalcontroller_WhenITryToApproveABasket_IGetTheCorrectViewReturned()
    {
      var approvalResults = new BatchApprovalResults();
      approvalResults.ApprovedDocuments.Add("guid1");

      this.approvalService.Setup(service => service.ApproveBasket("testUser", "testUser")).Returns(approvalResults);

      var result = (PartialViewResult)this.approvalController.Basket(this.approveDocumentsViewModel);
      var model = (DocumentWarningsViewModel)result.Model;
      model.DocumentsAlreadyApproved.Should().Be(String.Empty);
      model.DocumentsApproved.Should().Be(1);
      model.DocumentsRejected.Should().Be(0);
      result.ViewName.Should().Be("_DocumentWarnings");
    }
  }
}
